package com.ljs.module.util;

import com.ljs.module.entity.ConfigProperties;
import com.ljs.module.entity.language.Language;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 注入国际化文件
 * Created by lijunsai on 2021/07/12
 */
public class LanguageFileUtil {
    // 三个国际化文件
    private static String[] prosName = new String[]{"extension_lang_en.properties", "extension_lang_zh_CN.properties", "extension_lang_zh_TW.properties"};
    /**
     * 通过扩展包路径 注入国际化到文件中
     * @param path 扩展包路径
     * @return 处理结果
     * @throws IOException
     */
    public static String appendToProperties(String path, Map<String, Language> convertrMap, ConfigProperties configProperties) throws IOException {
        if (StringUtils.isBlank(path)) {
            return null;
        }
        if (path.indexOf(File.separator + "src" + File.separator + "web") != -1) {
            path += Util.replaceFileSeparor("/META-INF/");
        } else {
            path += Util.replaceFileSeparor("/src/web/META-INF/");
        }
        StringBuilder errorMsg = new StringBuilder();
        // 三个国际化文件
        PropertiesUtil en = new PropertiesUtil(path, prosName[0], "en", configProperties);
        PropertiesUtil zh = new PropertiesUtil(path, prosName[1], "zh", configProperties);
        PropertiesUtil tw = new PropertiesUtil(path, prosName[2], "tw", configProperties);
        Set<String> strings = convertrMap.keySet();
        for (String string : strings) {
            Language language = convertrMap.get(string);
            errorMsg.append(en.append(language));
            errorMsg.append(zh.append(language));
            errorMsg.append(tw.append(language));
        }
        en.close();
        zh.close();
        tw.close();
        if (errorMsg.length() == 0) {
            errorMsg.append("国际化文件更新成功<br>");
        }
        return errorMsg.toString();
    }

    /**
     * 国际化内部类
     */
    static class PropertiesUtil{
        FileOutputStream fos;
        Map<String, SmallLanguage> props = new HashMap<>();
        File file;
        String type;
        static String charset = "UTF-8";
        ConfigProperties configProperties = null;

        /**
         * 初始化国际化IO对象 键值对对象
         * @param path 国际化文件路径
         * @param fileName 国际化文件名称
         * @param type 国际化类型
         * @throws IOException
         */
        public PropertiesUtil(String path, String fileName, String type, ConfigProperties configProperties) throws IOException {
            file = new File(path, fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            props = getPropsMap(file);
            this.type = type;
            this.configProperties = configProperties;
        }

        /**
         * 追加到国际化文件
         * @param language 国际化值
         * @return 是否追加成功
         * @throws IOException
         */
        public String append(Language language) throws IOException {
            SmallLanguage smallLanguage = props.get(language.getEnToUppercase());
            if (smallLanguage != null) {
                if (configProperties.isOverride()) {
                    props.put(language.getEnToUppercase(), SmallLanguage.parse(language, type));
                    write(props, file);
                    return "国际化文件Key:" + language.getEnToUppercase() + "已存在，执行覆盖操作<br>";
                } else {
                    return "国际化文件Key:" + language.getEnToUppercase() + "已存在<br>";
                }

            } else {
                fos = new FileOutputStream(file, true);
                fos.write(("\r\n" + language.toStringByType(type, configProperties)).getBytes(charset));
                return "";
            }
        }

        /**
         * 读取properties文件 并且读到注释部分 封装成内部类SmallLanguage实体 方便在执行覆盖时将对应的注释也覆盖了
         * @param file 文件
         * @return 键值对
         * @throws IOException 异常
         */
        public static Map<String, SmallLanguage> getPropsMap(File file) throws IOException {
            Map<String, SmallLanguage> tempProps = new HashMap<>();
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset));
            SmallLanguage language = new SmallLanguage();
            String temp = "";
            while ((temp = br.readLine()) != null) {
                if (!StringUtils.isBlank(temp)) {
                    if (temp.contains("##")) {
                        String zh = temp.replaceAll("##", "").trim();
                        if (StringUtils.isBlank(language.zh)) {
                            language.zh = zh;
                        } else {
                            language.zh = language.zh + "\r\n" + zh;
                        }
                    } else if (temp.contains("=")){
                        String[] split = temp.split("=");
                        language.key = split[0].trim();
                        language.value = split[1].trim();
                        tempProps.put(language.key, language);
                        language = new SmallLanguage();
                    }
                }
            }
            br.close();
            return tempProps;
        }

        /**
         * 将国际化写回文件中
         * @param tempProps 键值对
         * @param file 文件
         * @throws IOException
         */
        public static void write(Map<String, SmallLanguage> tempProps, File file) throws IOException{
            FileOutputStream fos = new FileOutputStream(file);
            Set<String> keySet = tempProps.keySet();
            for (String key : keySet) {
                SmallLanguage value = tempProps.get(key);
                fos.write(value.toString().getBytes(charset));
            }
            fos.close();
        }

        public void close(){
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class SmallLanguage{
        public String key;
        public String value;
        public String zh;

        public static SmallLanguage parse(Language language, String type) {
            SmallLanguage smallLanguage = new SmallLanguage();
            smallLanguage.zh = language.getZh();
            smallLanguage.key = language.getEnToUppercase();
            switch (type) {
                case "en" : smallLanguage.value = language.getEnUnicode();break;
                case "zh" : smallLanguage.value = language.getZhUnicode();break;
                case "tw" : smallLanguage.value = language.getTwUnicode();break;
            }
            return smallLanguage;
        }

        public String toString(){
            String ret = "";
            if (!StringUtils.isBlank(zh)) {
                ret += "## " + zh + "\r\n";
            }
            ret += key + " = " + value + "\r\n";
            return ret;
        }
    }
}
